﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using Common.Logging;
using In.Api.Dto.HisWs;
using Newtonsoft.Json;
using Out.Service.HttpClients;
using OutDbContext;

namespace Out.Service.Services
{
    public class BizDepart : IDisposable
    {
        private static readonly ILog Logger = LogManager.GetLogger(typeof(BizDepart));
        private readonly GdsfybjyWeiXinEntities _ctx;
        private readonly string _deptId;

        public BizDepart()
        {
            _ctx = new GdsfybjyWeiXinEntities();
        }

        public BizDepart(string deptId)
        {
            _ctx = new GdsfybjyWeiXinEntities();
            _deptId = deptId;
        }

        /// <summary>
        /// 获取单个科室信息
        /// </summary>
        /// <returns></returns>
        public Depart Get()
        {
            var depart = _ctx.Departs.FirstOrDefault(x => x.DeptId == _deptId);
            return depart;
        }

        /// <summary>
        /// 获取所有科室
        /// </summary>
        /// <param name="branchNo">院区编号，为空时表示所有院区</param>
        /// <returns></returns>
        public List<Depart> GetAll(string branchNo = "")
        {
            var departs = _ctx.Departs.Where(x => x.RecStatus == 1);
            if (!string.IsNullOrEmpty(branchNo))
            {
                departs = departs.Where(x => x.BranchNo == branchNo);
            }

            var resDeparts = departs.OrderBy(x => x.Sort).ThenBy(x => x.DeptId).ToList();

            return resDeparts;
        }

        /// <summary>
        /// 搜索科室
        /// </summary>
        /// <param name="keyword">搜索关键字</param>
        /// <returns></returns>
        public List<Depart> Search(string keyword)
        {
            var departs = _ctx.Departs.Where(x => x.RecStatus == 1 && x.DeptName.Contains(keyword));

            var resDeparts = departs.OrderBy(x => x.Sort).ThenBy(x => x.DeptId).ToList();

            return resDeparts;
        }

        /// <summary>
        /// 获取科室或医生排班
        /// </summary>
        /// <param name="doctorId">医生院内编号，没有则表示查看该科室内所有医生的排班</param>
        /// <returns></returns>
        public RegSchedule GetSchedule(string doctorId)
        {
            var regSchedule = new RegSchedule();
            regSchedule.DeaultSelectedDay = "无剩余号源";
            regSchedule.Today = DateTime.Now.ToString("yyyy-MM-dd");
            regSchedule.RegDays = new List<RegSchedule.ScheduleDay>();
            for (int i = 0; i < 8; i++)
            {
                regSchedule.RegDays.Add(new RegSchedule.ScheduleDay
                {
                    Date = DateTime.Now.AddDays(i).ToString("yyyy-MM-dd"),
                    IsFull = true,
                    TimeSlices = new List<RegSchedule.TimeSlice>()
                });
            }

            //执行获取挂号费操作
            var request = new GetScheduleInfoRequest();
            request.DeptId = _deptId;
            request.DoctorId = doctorId;
            request.BeginDate = DateTime.Now.ToString("yyyy-MM-dd");
            request.EndDate = DateTime.Now.AddDays(7).ToString("yyyy-MM-dd");

            GetScheduleInfoResponse response;
            try
            {
                var httpClient = InHttpClient.GetClient();
                var responseMsg = httpClient.PostAsJsonAsync("HisWs/GetScheduleInfo", request).Result;
                responseMsg.EnsureSuccessStatusCode();
                response = responseMsg.Content.ReadAsAsync<GetScheduleInfoResponse>().Result;
            }
            catch (Exception ex)
            {
                Logger.ErrorFormat("调用院内排班Api出错,信息：{0}", JsonConvert.SerializeObject(ex));
                return regSchedule;
            }

            if (response.ResultCode != "0")
            {
                return regSchedule;
            }

            var scheduleInfos = response.ScheduleList;
            scheduleInfos.Sort(new ScheduleInfoComparer());

            foreach (var scheduleInfo in scheduleInfos)
            {
                //已停诊和已经结束的排班不显示
                if (scheduleInfo.IsHalt == "0" &&
                    (String.CompareOrdinal(scheduleInfo.RegDate, DateTime.Now.ToString("yyyy-MM-dd")) > 0
                    ||
                    (String.CompareOrdinal(scheduleInfo.RegDate, DateTime.Now.ToString("yyyy-MM-dd")) == 0
                        && String.CompareOrdinal(scheduleInfo.EndTime, DateTime.Now.ToString("HH:mm")) > 0)))
                {
                    //不限号的排班只可以做当日挂号，不做预约
                    if (scheduleInfo.TotalCount != "不限号" ||
                        (scheduleInfo.TotalCount == "不限号" &&
                         String.CompareOrdinal(scheduleInfo.RegDate, DateTime.Now.ToString("yyyy-MM-dd")) == 0))
                    {
                        //急诊号只能在排班开始后显示
                        if (scheduleInfo.RegType.IndexOf("急诊", StringComparison.Ordinal) < 0
                            || (scheduleInfo.RegType.IndexOf("急诊", StringComparison.Ordinal) >= 0
                                && String.CompareOrdinal(scheduleInfo.StartTime, DateTime.Now.ToString("HH:mm")) <= 0))
                        {
                            var scheduleDay = regSchedule.RegDays.First(x => x.Date == scheduleInfo.RegDate);
                            if (scheduleInfo.TotalCount == "不限号" || scheduleInfo.LeaveCount.ToInt32OrDefault() > 0)
                            {
                                scheduleDay.IsFull = false;
                                if (regSchedule.DeaultSelectedDay == "无剩余号源")
                                {
                                    regSchedule.DeaultSelectedDay = scheduleInfo.RegDate;
                                }
                            }

                            scheduleDay.TimeSlices.Add(new RegSchedule.TimeSlice
                            {
                                DeptId = scheduleInfo.DeptId,
                                DeptName = scheduleInfo.DeptName,
                                DoctorId = scheduleInfo.DoctorId,
                                DoctorName = scheduleInfo.DoctorName,
                                Title = scheduleInfo.Title,
                                RegType = scheduleInfo.RegType,
                                SliceName = scheduleInfo.TimeSlice,
                                SliceStartTime = scheduleInfo.StartTime,
                                SliceEndTime = scheduleInfo.EndTime,
                                LeaveCount = scheduleInfo.LeaveCount.ToInt32OrDefault() < 0 ? 0 : scheduleInfo.LeaveCount.ToInt32OrDefault(),
                                TotalCount = scheduleInfo.TotalCount.ToInt32OrDefault(),
                                HasTimePoint = scheduleInfo.IsTimeFlag == "1",
                                RegFee = scheduleInfo.Fee.ToDecimalOrDefault(),
                                TreatFee = scheduleInfo.TreatFee.ToDecimalOrDefault(),
                                OtherFee = scheduleInfo.OtherFee.ToDecimalOrDefault(),
                                TotalFee = scheduleInfo.Fee.ToDecimalOrDefault() + scheduleInfo.TreatFee.ToDecimalOrDefault() + scheduleInfo.OtherFee.ToDecimalOrDefault()
                            });
                        }
                    }
                }
            }

            return regSchedule;
        }

        public void Dispose()
        {
            _ctx.Dispose();
        }
    }

    public class RegSchedule
    {
        /// <summary>
        /// 当日 yyyy-MM-dd
        /// </summary>
        public string Today { get; set; }

        /// <summary>
        /// 当前默认已选日期，原则上选择最近的有号的日期 yyyy-MM-dd
        /// 如果所有都没有有号的日期，那么 defaultSelectedDay = '无剩余号源'
        /// </summary>
        public string DeaultSelectedDay { get; set; }

        /// <summary>
        /// 排班的日期列表
        /// </summary>
        public List<ScheduleDay> RegDays { get; set; }

        public class ScheduleDay
        {
            /// <summary>
            /// 日期 yyyy-MM-dd
            /// </summary>
            public string Date { get; set; }

            /// <summary>
            /// 是否已约满
            /// </summary>
            public bool IsFull { get; set; }

            /// <summary>
            /// 时段
            /// </summary>
            public List<TimeSlice> TimeSlices { get; set; }
        }

        public class TimeSlice
        {
            /// <summary>
            ///     科室编码
            /// </summary>
            public string DeptId { get; set; }

            /// <summary>
            ///     科室名称
            /// </summary>
            public string DeptName { get; set; }

            /// <summary>
            ///     医生编码
            /// </summary>
            public string DoctorId { get; set; }

            /// <summary>
            ///     医生名称
            /// </summary>
            public string DoctorName { get; set; }

            /// <summary>
            ///     医生职称
            /// </summary>
            public string Title { get; set; }

            /// <summary>
            /// 号类
            /// </summary>
            public string RegType { get; set; }

            /// <summary>
            /// 时段名称
            /// </summary>
            public string SliceName { get; set; }

            /// <summary>
            /// 时段开始时间
            /// </summary>
            public string SliceStartTime { get; set; }

            /// <summary>
            /// 时段结束时间
            /// </summary>
            public string SliceEndTime { get; set; }

            /// <summary>
            /// 剩余号数
            /// 0 时表示 已约满
            /// </summary>
            public int LeaveCount { get; set; }

            /// <summary>
            /// 总号数
            /// 0 表示 不限号
            /// </summary>
            public int TotalCount { get; set; }

            /// <summary>
            /// 是否有分时
            /// </summary>
            public bool HasTimePoint { get; set; }

            /// <summary>
            /// 挂号费
            /// </summary>
            public decimal RegFee { get; set; }

            /// <summary>
            /// 诊疗费
            /// </summary>
            public decimal TreatFee { get; set; }

            /// <summary>
            /// 其他费
            /// </summary>
            public decimal OtherFee { get; set; }

            /// <summary>
            /// 总费用
            /// </summary>
            public decimal TotalFee { get; set; }
        }
    }

    public class ScheduleInfoComparer : IComparer<GetScheduleInfoResponse.ScheduleInfo>
    {
        public int Compare(GetScheduleInfoResponse.ScheduleInfo x, GetScheduleInfoResponse.ScheduleInfo y)
        {
            var rtn = String.Compare(x.RegDate, y.RegDate, StringComparison.Ordinal);
            if (rtn == 0)
            {
                if (x.TotalCount == "不限号" && y.TotalCount != "不限号")
                {
                    return -1;
                }
                if (x.TotalCount != "不限号" && y.TotalCount == "不限号")
                {
                    return 1;
                }

                if (x.LeaveCount.ToInt32OrDefault() > 0 && y.LeaveCount.ToInt32OrDefault() <= 0)
                {
                    return -1;
                }
                if (x.LeaveCount.ToInt32OrDefault() <= 0 && y.LeaveCount.ToInt32OrDefault() > 0)
                {
                    return 1;
                }

                rtn = String.Compare(x.StartTime, y.StartTime, StringComparison.Ordinal);
                if (rtn == 0)
                {
                    var titles = new[] { "主任医师", "副主任医师", "主治医师", "医师" };

                    rtn = titles.IndexOf(x.Title).CompareTo(titles.IndexOf(y.Title));
                }
            }
            return rtn;
        }
    }
}